/*
 * To change this template, choose Tools | Templates and open the template in
 * the editor.
 */
package goodenglish.interfaces.videoplay;

import goodenglish.domain.model.subt.Subt;
import goodenglish.domain.model.subt.SubtRepository;
import goodenglish.infrastructure.Config;
import goodenglish.infrastructure.repository.db.SubtRepositoryDb;
import goodenglish.interfaces.BeanFactory;
import goodenglish.interfaces.Main;
import goodenglish.interfaces.MenuToolBar;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.util.Duration;

/**
 * 
 * @author 关攀攀 panpan_001@126.com
 */
public class MediaPane extends BorderPane {
	private String MEDIA_URL;
	MediaPlayer mediaPlayer;
	private MediaView mediaView;
	private final boolean repeat = false;
	private boolean stopRequested = false;
	private boolean atEndOfMedia = false;
	Duration duration;
	Slider timeSlider;
	Label playTime;
	private Slider volumeSlider;
	private HBox mediaBar;
	private static final Image PlayButtonImage = new Image(MediaPane.class.getResourceAsStream("playbutton.png"));
	private static final Image PauseButtonImage = new Image(MediaPane.class.getResourceAsStream("pausebutton.png"));
	ImageView imageViewPlay = new ImageView(PlayButtonImage);
	ImageView imageViewPause = new ImageView(PauseButtonImage);
	final Button playButton = new Button();

	@Override
	protected void layoutChildren() {
		if (mediaView != null && getBottom() != null) {
			mediaView.setFitWidth(getWidth());
			mediaView.setFitHeight(getHeight() - getBottom().prefHeight(-1));
		}
		super.layoutChildren();
		if (mediaView != null) {
			mediaView.setTranslateX((((Pane) getCenter()).getWidth() - mediaView.prefWidth(-1)) / 2);
			mediaView.setTranslateY((((Pane) getCenter()).getHeight() - mediaView.prefHeight(-1)) / 2);
		}
	}

	@Override
	protected double computeMinWidth(double height) {
		return mediaBar.prefWidth(-1);
	}

	@Override
	protected double computeMinHeight(double width) {
		return 200;
	}

	@Override
	protected double computePrefWidth(double height) {
		return Math.max(mediaPlayer.getMedia().getWidth(), mediaBar.prefWidth(height));
	}

	@Override
	protected double computePrefHeight(double width) {
		return mediaPlayer.getMedia().getHeight() + mediaBar.prefHeight(width);
	}

	@Override
	protected double computeMaxWidth(double height) {
		return Double.MAX_VALUE;
	}

	@Override
	protected double computeMaxHeight(double width) {
		return Double.MAX_VALUE;
	}

	public MediaPane(String filePath) {
		MEDIA_URL = "file:///" + filePath.replaceAll("\\\\", "/");

		this.mediaPlayer = new MediaPlayer(new Media(MEDIA_URL));
		String name = MEDIA_URL.split("/")[MEDIA_URL.split("/").length - 1].split("\\.")[0];
		subt = subtRepository.getSubtByName(name);
		this.mediaPlayer.setAutoPlay(true);
		setStyle("-fx-background-color: #bfc2c7;"); // TODO: Use css file
		addMediaViewToCenter();
		addMediaBarToBottom();

		this.setMinSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT + 100);
		this.setPrefSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT + 100);
		// mediaControl.setMaxSize(480, 280);
		this.setLayoutY(0);
		// 添加播放面板
		this.play();
		// 添加播放器设置
		this.setOnMousePressed(new EventHandler<MouseEvent>() {

			public void handle(MouseEvent t) {
				if (t.isSecondaryButtonDown()) {
					new PlaySetingDialog(MediaPane.this);
				}
			}
		});
		this.setOnKeyPressed(new EventHandler<KeyEvent>() {

			public void handle(KeyEvent t) {
				if (t.getCode().equals(KeyCode.A)) {
					PlayRegion.manCanceled = true;
				}
				if (t.getCode().equals(KeyCode.ESCAPE)) {
					MediaPane.this.cancleFullScreen();
				}
				if (t.getCode().equals(KeyCode.F1)) {
					MediaPane.this.setFullScreen();
				}

			}
		});
		this.setFullScreen();
	}

	public void cancleFullScreen() {
		Main.stage.setFullScreen(false);
		Main.root.setTop(BeanFactory.getSingleInstance(MenuToolBar.class));
		this.setLayoutY(Config.MENU_HEIGHT);
		this.setMinSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT - Config.MENU_HEIGHT);
		this.setPrefSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT - Config.MENU_HEIGHT);
	}

	public void setFullScreen() {
		this.setLayoutY(0);
		Main.stage.setFullScreen(true);
		Main.root.setTop(null);
		this.setMinSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT + 100);
		this.setPrefSize(Config.SCREEN_WIDTH, Config.SCREEN_HEIGHT + 100);
	}

	private void addMediaBarToBottom() {
		mediaBar = new HBox();
		mediaBar.setPadding(new Insets(5, 10, 5, 10));
		mediaBar.setAlignment(Pos.CENTER_LEFT);
		BorderPane.setAlignment(mediaBar, Pos.CENTER);
		addPlayButton();
		addMediaPlayerListener();

		// Add spacer
		Label spacer = new Label("   ");
		mediaBar.getChildren().add(spacer);
		addTimeSlider();
		addTimeView();
		addVolumeSlider();
		setBottom(mediaBar);
	}

	private void addVolumeSlider() {
		// Volume label
		Label volumeLabel = new Label("Vol: ");
		mediaBar.getChildren().add(volumeLabel);
		// Volume slider
		volumeSlider = new Slider();
		volumeSlider.setPrefWidth(70);
		volumeSlider.setMaxWidth(Region.USE_PREF_SIZE);
		volumeSlider.setMinWidth(30);
		volumeSlider.valueProperty().addListener(new InvalidationListener() {

			public void invalidated(Observable ov) {
			}
		});

		volumeSlider.valueProperty().addListener(new ChangeListener<Number>() {

			@Override
			public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				if (volumeSlider.isValueChanging()) {
					mediaPlayer.setVolume(volumeSlider.getValue() / 100.0);
				}
			}
		});
		mediaBar.getChildren().add(volumeSlider);
	}

	private void addTimeView() {
		// Play label
		playTime = new Label();
		playTime.setPrefWidth(130);
		playTime.setMinWidth(50);
		mediaBar.getChildren().add(playTime);
	}

	private void addTimeSlider() {
		Label timeLabel = new Label("Time: ");
		mediaBar.getChildren().add(timeLabel);

		// Time slider
		timeSlider = new Slider();
		HBox.setHgrow(timeSlider, Priority.ALWAYS);
		timeSlider.setMinWidth(50);
		timeSlider.setMaxWidth(Double.MAX_VALUE);
		timeSlider.valueProperty().addListener(new InvalidationListener() {

			public void invalidated(Observable ov) {
				if (timeSlider.isValueChanging()) {
					// multiply duration by percentage calculated by slider
					// position
					if (duration != null) {
						mediaPlayer.seek(duration.multiply(timeSlider.getValue() / 100.0));
					}
					updateValues();

				}
			}
		});
		mediaBar.getChildren().add(timeSlider);
	}

	private void addMediaPlayerListener() {
		if (subt != null) {
			// 当播放时更新播放状态显示
			mediaPlayer.currentTimeProperty().addListener(new SubtShowListener(this));
			// 播放字幕学习及重播放
			if (Config.PLAY_MODE.equals(PlayMode.STUDY_SUBT)) {
				mediaPlayer.currentTimeProperty().addListener(new StudyListener(this));
			}

		}

		mediaPlayer.setOnPlaying(new Runnable() {

			public void run() {
				// System.out.println("onPlaying");
				if (stopRequested) {
					mediaPlayer.pause();
					stopRequested = false;
				} else {
					playButton.setGraphic(imageViewPause);
					// playButton.setText("||");
				}
			}
		});
		mediaPlayer.setOnPaused(new Runnable() {

			public void run() {
				// System.out.println("onPaused");
				playButton.setGraphic(imageViewPlay);
				// playButton.setText("||");
			}
		});
		mediaPlayer.setOnReady(new Runnable() {

			public void run() {
				duration = mediaPlayer.getMedia().getDuration();
				System.out.println("b:" + duration);
				System.out.println("b:" + DurationHelper.formatTime(mediaPlayer.getCurrentTime(), duration));
				updateValues();
			}
		});

		mediaPlayer.setCycleCount(repeat ? MediaPlayer.INDEFINITE : 1);
		mediaPlayer.setOnEndOfMedia(new Runnable() {

			public void run() {
				if (!repeat) {
					playButton.setGraphic(imageViewPlay);
					// playButton.setText(">");
					stopRequested = true;
					atEndOfMedia = true;
				}
			}
		});
	}

	/**
	 * 添加播放按钮
	 */
	private void addPlayButton() {

		playButton.setGraphic(imageViewPlay);
		playButton.setOnAction(new EventHandler<ActionEvent>() {

			public void handle(ActionEvent e) {
				// 更新相关状态显示
				updateValues();

				MediaPlayer.Status status = mediaPlayer.getStatus();

				// 如果状态不是可播放的状态，则返回
				if (status == MediaPlayer.Status.UNKNOWN || status == MediaPlayer.Status.HALTED) {
					// don't do anything in these states
					return;
				}
				// 如果状态是可播放的状态，进行播放，如果正在播放就暂停
				if (status == MediaPlayer.Status.PAUSED || status == MediaPlayer.Status.READY
						|| status == MediaPlayer.Status.STOPPED) {
					// 如果已经结束就重播，把时间设置成影片开始时间
					if (atEndOfMedia) {
						mediaPlayer.seek(mediaPlayer.getStartTime());
						atEndOfMedia = false;
						playButton.setGraphic(imageViewPlay);
						// playButton.setText(">");
						updateValues();
					}
					mediaPlayer.play();
					playButton.setGraphic(imageViewPause);
					// playButton.setText("||");
				} else {
					mediaPlayer.pause();
				}

			}
		});
		mediaBar.getChildren().add(playButton);
	}

	private void addMediaViewToCenter() {
		// 添加播放区域,新未知为什么要放在一个Pane里
		mediaView = new MediaView(mediaPlayer);
		Pane mediaViewPane = new Pane() {
		};
		mediaViewPane.getChildren().add(mediaView);
		mediaViewPane.setStyle("-fx-background-color: black;"); // TODO: Use css
																// file
		setCenter(mediaViewPane);
	}

	public void play() {
		MediaPlayer.Status status = mediaPlayer.getStatus();
		if (status == MediaPlayer.Status.UNKNOWN || status == MediaPlayer.Status.HALTED) {
			// System.out.println("Player is in a bad or unknown state, can't play.");
			return;
		}

		if (status == MediaPlayer.Status.PAUSED || status == MediaPlayer.Status.STOPPED
				|| status == MediaPlayer.Status.READY) {
			mediaPlayer.play();
		}
	}

	public void stop() {
		mediaPlayer.stop();
	}

	/**
	 * 更新按钮栏显示
	 */
	protected void updateValues() {
		if (playTime != null && timeSlider != null && volumeSlider != null && duration != null) {
			Platform.runLater(new Runnable() {

				public void run() {

					Duration currentTime = mediaPlayer.getCurrentTime();
					playTime.setText(DurationHelper.formatTime(currentTime, duration));
					timeSlider.setDisable(duration.isUnknown());
					if (!timeSlider.isDisabled() && duration.greaterThan(Duration.ZERO) && !timeSlider.isValueChanging()) {
						timeSlider.setValue(currentTime.divide(duration).toMillis() * 100.0);
					}
					if (!volumeSlider.isValueChanging()) {
						volumeSlider.setValue((int) Math.round(mediaPlayer.getVolume() * 100));
					}

				}
			});
		}
	}

	private SubtRepository subtRepository = BeanFactory.getSingleInstance(SubtRepositoryDb.class);
	Subt subt;

}
